/****************************************************************
 * Fulguro
 * Copyright (C) 2004 Christophe Clienti
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 ***************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <flgrCoreDispatch.h>
#include <flgrCoreSlideWindow.h>
#include <flgrCoreNhbManage.h>
#include "flgrLinearKerOp.h"
#include "flgrLinearConvolution.h"

/*!
 * \defgroup group_fulguro_linear_conv Convolution
 * \ingroup group_fulguro_linear
 * Convolution operations
 * @{
 */


void flgr1d_convolution_fgBIT(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb) {
  flgr_no_define_type_function(FLGR_BIT);
}
void flgr1d_convolution_fgUINT8(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr1d_raster_slide_window_fgUINT8(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, flgr1d_get_nhb_convolution_fgUINT8);
}
void flgr1d_convolution_fgUINT16(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr1d_raster_slide_window_fgUINT16(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, flgr1d_get_nhb_convolution_fgUINT16);
}
void flgr1d_convolution_fgUINT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr1d_raster_slide_window_fgUINT32(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, flgr1d_get_nhb_convolution_fgUINT32);
}
void flgr1d_convolution_fgINT8(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr1d_raster_slide_window_fgINT8(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, flgr1d_get_nhb_convolution_fgINT8);
}
void flgr1d_convolution_fgINT16(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr1d_raster_slide_window_fgINT16(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, flgr1d_get_nhb_convolution_fgINT16);
}
void flgr1d_convolution_fgINT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr1d_raster_slide_window_fgINT32(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, flgr1d_get_nhb_convolution_fgINT32);
}
void flgr1d_convolution_fgFLOAT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr1d_raster_slide_window_fgFLOAT32(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, flgr1d_get_nhb_convolution_fgFLOAT32);
}
void flgr1d_convolution_fgFLOAT64(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr1d_raster_slide_window_fgFLOAT64(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, flgr1d_get_nhb_convolution_fgFLOAT64);
}



//////////////////////////////////////////////////////////////////
/*! Compute a convolution.
 *  @param datdest : a pointer to FLGR_Data1D
 *  @param datsrc : a pointer to FLGR_Data1D
 *  @param nhb : a pointer to FLGR_Data1D
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr1d_convolution(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb) {
  FLGR_Ret ret;

  FLGR_DECLARE_FUNCTION;

  if((datdest==NULL) || (datsrc==NULL) || (nhb==NULL)){
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if((ret=flgr1d_is_data_same_attributes(datdest,datsrc,__FUNCTION__)) != FLGR_RET_OK) return ret;

  FLGR_DISPATCH_PROCEDURE(datdest->type,flgr1d_convolution,datdest,datsrc,nhb);

}






void flgr1d_convolution_unfolded_fgBIT(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb) {
  flgr_no_define_type_function(FLGR_BIT);
}
void flgr1d_convolution_unfolded_fgUINT8(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr1d_raster_slide_window_unfolded_fgUINT8(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, 
					    flgr1d_get_nhb_convolution_fgUINT8);
}
void flgr1d_convolution_unfolded_fgUINT16(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr1d_raster_slide_window_unfolded_fgUINT16(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, 
					     flgr1d_get_nhb_convolution_fgUINT16);
}
void flgr1d_convolution_unfolded_fgUINT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr1d_raster_slide_window_unfolded_fgUINT32(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, 
					     flgr1d_get_nhb_convolution_fgUINT32);
}
void flgr1d_convolution_unfolded_fgINT8(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr1d_raster_slide_window_unfolded_fgINT8(datdest, datsrc, nhb, FLGR_NHB_NO_SYM,
					   flgr1d_get_nhb_convolution_fgINT8);
}
void flgr1d_convolution_unfolded_fgINT16(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr1d_raster_slide_window_unfolded_fgINT16(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, 
					    flgr1d_get_nhb_convolution_fgINT16);
}
void flgr1d_convolution_unfolded_fgINT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr1d_raster_slide_window_unfolded_fgINT32(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, 
					    flgr1d_get_nhb_convolution_fgINT32);
}
void flgr1d_convolution_unfolded_fgFLOAT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr1d_raster_slide_window_unfolded_fgFLOAT32(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, 
					      flgr1d_get_nhb_convolution_fgFLOAT32);
}
void flgr1d_convolution_unfolded_fgFLOAT64(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr1d_raster_slide_window_unfolded_fgFLOAT64(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, 
					      flgr1d_get_nhb_convolution_fgFLOAT64);
}



//////////////////////////////////////////////////////////////////
/*! Compute a convolution (image is unfolded for border processing).
 *  @param datdest : a pointer to FLGR_Data1D
 *  @param datsrc : a pointer to FLGR_Data1D
 *  @param nhb : a pointer to FLGR_Data1D
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr1d_convolution_unfolded(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb) {
  FLGR_Ret ret;

  FLGR_DECLARE_FUNCTION;

  if((datdest==NULL) || (datsrc==NULL) || (nhb==NULL)){
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if((ret=flgr1d_is_data_same_attributes(datdest,datsrc,__FUNCTION__)) != FLGR_RET_OK) return ret;

  FLGR_DISPATCH_PROCEDURE(datdest->type,flgr1d_convolution_unfolded,datdest,datsrc,nhb);

}













void flgr2d_convolution_fgBIT(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  flgr_no_define_type_function(FLGR_BIT);
}
void flgr2d_convolution_fgUINT8(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr2d_raster_slide_window_fgUINT8(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, flgr2d_get_nhb_convolution_fgUINT8);
}
void flgr2d_convolution_fgUINT16(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr2d_raster_slide_window_fgUINT16(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, flgr2d_get_nhb_convolution_fgUINT16);
}
void flgr2d_convolution_fgUINT32(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr2d_raster_slide_window_fgUINT32(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, flgr2d_get_nhb_convolution_fgUINT32);
}
void flgr2d_convolution_fgINT8(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr2d_raster_slide_window_fgINT8(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, flgr2d_get_nhb_convolution_fgINT8);
}
void flgr2d_convolution_fgINT16(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr2d_raster_slide_window_fgINT16(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, flgr2d_get_nhb_convolution_fgINT16);
}
void flgr2d_convolution_fgINT32(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr2d_raster_slide_window_fgINT32(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, flgr2d_get_nhb_convolution_fgINT32);
}
void flgr2d_convolution_fgFLOAT32(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr2d_raster_slide_window_fgFLOAT32(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, flgr2d_get_nhb_convolution_fgFLOAT32);
}
void flgr2d_convolution_fgFLOAT64(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr2d_raster_slide_window_fgFLOAT64(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, flgr2d_get_nhb_convolution_fgFLOAT64);
}



//////////////////////////////////////////////////////////////////
/*! Compute a convolution.
 *  @param datdest : a pointer to FLGR_Data2D
 *  @param datsrc : a pointer to FLGR_Data2D
 *  @param nhb : a pointer to FLGR_Data2D
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_convolution(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  FLGR_Ret ret;

  FLGR_DECLARE_FUNCTION;

  if((datdest==NULL) || (datsrc==NULL) || (nhb==NULL)){
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if((ret=flgr2d_is_data_same_attributes(datdest,datsrc,__FUNCTION__)) != FLGR_RET_OK) return ret;

  FLGR_DISPATCH_PROCEDURE(datdest->type,flgr2d_convolution,datdest,datsrc,nhb);

}






void flgr2d_convolution_unfolded_fgBIT(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  flgr_no_define_type_function(FLGR_BIT);
}
void flgr2d_convolution_unfolded_fgUINT8(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr2d_raster_slide_window_unfolded_fgUINT8(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, 
					    flgr2d_get_nhb_convolution_fgUINT8);
}
void flgr2d_convolution_unfolded_fgUINT16(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr2d_raster_slide_window_unfolded_fgUINT16(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, 
					     flgr2d_get_nhb_convolution_fgUINT16);
}
void flgr2d_convolution_unfolded_fgUINT32(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr2d_raster_slide_window_unfolded_fgUINT32(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, 
					     flgr2d_get_nhb_convolution_fgUINT32);
}
void flgr2d_convolution_unfolded_fgINT8(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr2d_raster_slide_window_unfolded_fgINT8(datdest, datsrc, nhb, FLGR_NHB_NO_SYM,
					   flgr2d_get_nhb_convolution_fgINT8);
}
void flgr2d_convolution_unfolded_fgINT16(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr2d_raster_slide_window_unfolded_fgINT16(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, 
					    flgr2d_get_nhb_convolution_fgINT16);
}
void flgr2d_convolution_unfolded_fgINT32(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr2d_raster_slide_window_unfolded_fgINT32(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, 
					    flgr2d_get_nhb_convolution_fgINT32);
}
void flgr2d_convolution_unfolded_fgFLOAT32(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr2d_raster_slide_window_unfolded_fgFLOAT32(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, 
					      flgr2d_get_nhb_convolution_fgFLOAT32);
}
void flgr2d_convolution_unfolded_fgFLOAT64(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr2d_raster_slide_window_unfolded_fgFLOAT64(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, 
					      flgr2d_get_nhb_convolution_fgFLOAT64);
}



//////////////////////////////////////////////////////////////////
/*! Compute a convolution (image is unfolded for border processing).
 *  @param datdest : a pointer to FLGR_Data2D
 *  @param datsrc : a pointer to FLGR_Data2D
 *  @param nhb : a pointer to FLGR_Data2D
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_convolution_unfolded(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  FLGR_Ret ret;

  FLGR_DECLARE_FUNCTION;

  if((datdest==NULL) || (datsrc==NULL) || (nhb==NULL)){
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if((ret=flgr2d_is_data_same_attributes(datdest,datsrc,__FUNCTION__)) != FLGR_RET_OK) return ret;

  FLGR_DISPATCH_PROCEDURE(datdest->type,flgr2d_convolution_unfolded,datdest,datsrc,nhb);

}


//! @}
